/**
 * 异步 Action
 * 参考：http://www.cnblogs.com/xianyulaodi/p/5621959.html
 */
import { createStore, applyMiddleware } from 'redux'

/**
 * 引入中间件middleware
 * redux-thunk 是一个比较流行的 redux 异步 action 中间件
 */
import thunkMiddleware from "redux-thunk"

/**
 * 对 fetch 的扩展
 */
import fetch from 'isomorphic-fetch'


/**
 * Action Creators 
 */
function inc() {
  return { type: 'INCREMENT' };
}

function dec() {
  return { type: 'DECREMENT' };
}

var id = 1
function addTodo(content) {
  return {
    type: 'ADD_TODO',
    payload: {
      id: id++,
      content: content, // 待办事项内容
      completed: false  // 是否完成的标识
    }
  }
}


/**
 * 返回的不是一个action，而是一个function。这个返回值无法被reducer识别。
 * 也就是说，正常来说，action返回的是一个对象，而不是一个函数。如果返回函数，会出现错误。
 */
function testAsync(message) {
  setTimeout(function () {
    return {
      type: "SAY",
      message
    }
  }, 2000)
}


/**
 * 需要引入中间件middleware,它在中间起到了桥梁的作用，让action的返回值可以是一个函数，从而传到reducer那里
 * Middleware 主要是负责改变Store中的dispatch方法，从而能处理不同类型的 action 输入，
 * 得到最终的 Javascript Plain Object 形式的 action 对象
 * 这里使用 redux-thunk
 */
function test2Async(message) {
  return function (dispatch) {
    setTimeout(function () {
      dispatch({
        type: "SAY",
        message
      })
    }, 2000)
  }
}


/**
 * Sample Async Action namely: the thunk
 * 要配合redux-thunk这个middleware一起食用
 * ref: https://github.com/gaearon/redux-thunk
 */
function loadMoreWorkAsync() {
  /* TODO: 请暂时无视我如此拙劣的dispatch行为 */
  return function (dispatch) {
    /* 1. fetch之前，可以先发个pending的action */
    dispatch({
      type: "LOAD_MORE_WORK_pending",
      msg: 'pending',
    });
    fetch('test.txt').then(resp => {
      // console.log('[resp]', resp.status);
      if (resp.status === 200) return resp.json();
      throw new Error('not 200 this time'); // 美滴很
    }).then(json => {
      /* 2. 异步结束了，发结果action */
      dispatch({
        type: "LOAD_MORE_WORK_end",
        msg: json.name,
      });
    }).catch(error => {
      /* 3. 倒霉催的，发报错action */
      dispatch({
        type: "LOAD_MORE_WORK_error",
        msg: error,
      });
    });
  }
};


/**
 * Reducer
 */
function reducer(state, action) {
  // 首次调用本函数时设置初始 state
  state = state || {
    counter: 0,
    todos: []
  };

  switch (action.type) {
    case 'INCREMENT':
      return Object.assign({}, state, { counter: state.counter + 1 });
    case 'DECREMENT':
      //return { counter: state.counter - 1 };
      return Object.assign({}, state, { counter: state.counter - 1 });
    case "ADD_TODO":
      var nextState = Object.assign({}, state, { todos: [...state.todos, action.payload] })
      return nextState;
    case "SAY":
      console.debug("异步 Action \r\n" + action.message);
      return state;
    case "LOAD_MORE_WORK_pending":
      console.debug("LOAD_MORE_WORK_pending");
      return state;
    case "LOAD_MORE_WORK_end":
      console.debug("LOAD_MORE_WORK_end");
      return state;
    case "LOAD_MORE_WORK_error":
      console.debug("LOAD_MORE_WORK_error");
      return state;
    default:
      return state; // 无论如何都返回一个 state
  }
}


/**
 * Store
 */
var store = createStore(reducer, applyMiddleware(thunkMiddleware));


/**
 * dispatch
 */
console.log(store.getState()); // { counter: 0 }

store.dispatch(inc());
console.log(store.getState()); // { counter: 1 }

store.dispatch(inc());
console.log(store.getState()); // { counter: 2 }

store.dispatch(dec());
console.log(store.getState()); // { counter: 1 }

store.dispatch(addTodo("abc"));
console.log(store.getState());

//store.dispatch(testAsync("aa"));
store.dispatch(test2Async("aa"));
store.dispatch(loadMoreWorkAsync());